﻿using OpenIddict.Abstractions;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.OpenIddict.Scopes;

namespace mozhi.smarterp.AuthorCenter.Identities
{
    public class OpenIddictScopeAppService : AuthorCenterAppService, IOpenIddictScopeAppService
    {
        private readonly IOpenIddictScopeManager _scopeManager;
        public OpenIddictScopeAppService(IOpenIddictScopeManager scopeManager)
        {
            _scopeManager = scopeManager;
        }

        public async Task<OpenIddictScopeDto> CreateAsync(OpenIddictScopeCreateDto input)
        {
            var match = await _scopeManager.FindByNameAsync(input.Name);

            if (match != null)
                throw new UserFriendlyException($"已存在scope:{input.Name}");

            var createScope = new OpenIddictScopeDescriptor
            {
                Name = input.Name,
                DisplayName = input.DisplayName
            };

            if (input.Resources != null && input.Resources.Count > 0)
            {
                foreach (var resource in input.Resources)
                {
                    createScope.Resources.Add(resource);
                }
            }

            var scope = await _scopeManager.CreateAsync(createScope) as OpenIddictScopeModel;

            var result = new OpenIddictScopeDto();

            result.Name = scope.Name;
            result.DisplayName = scope.DisplayName;
            result.Resources = scope.Resources;

            return result;
        }

        public async Task DeleteAsync(string name)
        {
            var scope = await _scopeManager.FindByNameAsync(name) as OpenIddictScopeModel;

            if (scope == null)
                throw new UserFriendlyException($"scope:{name}不存在", "100000");

            await _scopeManager.DeleteAsync(scope);
        }

        public async Task<OpenIddictScopeDto> GetAsync(string name)
        {
            var scope = await _scopeManager.FindByNameAsync(name) as OpenIddictScopeModel;

            if (scope == null)
                throw new UserFriendlyException($"scope:{name}不存在", "100000");

            var result = new OpenIddictScopeDto();

            result.Name = scope.Name;
            result.DisplayName = scope.DisplayName;
            result.Resources = scope.Resources;

            return result;
        }

        public async Task<PagedResultDto<OpenIddictScopeDto>> GetListAsync(PagedResultRequestDto filter)
        {
            var count = await _scopeManager.CountAsync();

            if (count == 0)
                return new PagedResultDto<OpenIddictScopeDto>();

            var items = new List<OpenIddictScopeDto>();

            await foreach (OpenIddictScopeModel scope in _scopeManager.ListAsync(filter.MaxResultCount, filter.SkipCount))
            {
                var item = new OpenIddictScopeDto();

                item.Name = scope.Name;
                item.DisplayName = scope.DisplayName;
                item.Resources = scope.Resources;

                items.Add(item);
            }

            return new PagedResultDto<OpenIddictScopeDto>()
            {
                Items = items,
                TotalCount = count
            };
        }

        public async Task<OpenIddictScopeDto> UpdateAsync(OpenIddictScopeUpdateDto input)
        {
            var scope = await _scopeManager.FindByNameAsync(input.Name) as OpenIddictScopeModel;

            if (scope == null)
                throw new UserFriendlyException($"scope:{input.Name}不存在", "100000");

            await _scopeManager.DeleteAsync(scope);

            var createScope = new OpenIddictScopeDescriptor();
            createScope.Name = input.Name;
            createScope.DisplayName = input.DisplayName;
            createScope.Resources.Clear();

            if (input.Resources != null && input.Resources.Count > 0)
            {
                foreach (var resource in input.Resources)
                {
                    createScope.Resources.Add(resource);
                }
            }

            scope = await _scopeManager.CreateAsync(createScope) as OpenIddictScopeModel;

            var result = new OpenIddictScopeDto();

            result.Name = scope.Name;
            result.DisplayName = scope.DisplayName;
            result.Resources = scope.Resources;

            return result;
        }
    }
}
